#include "stdafx.hpp"
#include "ColligereMainFrame.hpp"
#include "ColligereAudioDatabaseInterface.hpp"

#include "ColligereConfigHandler.hpp"
#include "ColligereApp.hpp"

#include "ColligerePrefDialog.hpp"
#include "ColligereAboutDialog.hpp"
#include "ColligereSearchDialog.hpp"

#include "ColligereIds.hpp"

#include "ColligereDatabaseError.hpp"

IMPLEMENT_DYNAMIC_CLASS ( col::MainFrame, wxFrame );

col::MainFrame::MainFrame() : wxFrame ( NULL, wxID_ANY, wxGetApp().GetAppName() ), 
mpFileOprTb(0), mpItemOprTb(0), mpLogDlg(0)
{
	mFrameMngr.SetManagedWindow ( this );

	mpLogDlg = new LogDialog ( this );
	wxLog::SetActiveTarget ( new wxLogGui );
	new wxLogChain ( new HtmlLog ( mpLogDlg->GetLogCtrl() ) );

	CreateMenuBar();
	CreateToolBars();

	wxToolTip::Enable ( ConfigHandler::Get().IsEnabled ( ConfigVariable::ShowToolTips ) );

	AutoCompleteControlBase::EnableAutoComplete
		( !ConfigHandler::Get().IsEnabled ( ConfigVariable::DisableAutoComplete ) );

	CreateStatusBar(3);

	SetSize ( DetermineFrameSize().GetSize() );

	EnableFileOperations ( false );
	EnableItemOperations ( false );

	ConnectGuiEventHandlers();

	LoadLayout();

	SetDropTarget ( new DatabaseDropTarget ( this ) );
	wxIcon app_icon ( "appicon", wxBITMAP_TYPE_ICO_RESOURCE );
	wxASSERT ( app_icon.IsOk() );
	SetIcon ( app_icon );
	SetStatusText ( _("Ready"), 0 );

	ConfigHandler::Get().LoadFileHistory ( mFileHistory );

	mFrameMngr.Update();
}

col::MainFrame::~MainFrame()
{
	mFrameMngr.UnInit();
}

void col::MainFrame::CreateToolBars()
{
	const bool show_tooltips = ConfigHandler::Get().IsEnabled 
		( ConfigVariable::ShowToolTips );

	const wxInt32 style = show_tooltips ? 
		( wxAUI_TB_GRIPPER ) : ( wxAUI_TB_GRIPPER | wxAUI_TB_NO_TOOLTIPS );

    mpFileOprTb = new wxAuiToolBar ( this, wxID_ANY, wxDefaultPosition, 
		wxDefaultSize, style );
	mpFileOprTb->SetToolBitmapSize ( wxSize ( 16, 16 ) );

	typedef ColligereApp::IconIndex ii;

	CreateToolBarItem ( mpFileOprTb, wxID_NEW, _("New"), "", ii::FileNew );
	CreateToolBarItem ( mpFileOprTb, wxID_OPEN, _("Open"), "", ii::FileOpen );
	CreateToolBarItem ( mpFileOprTb, wxID_SAVE, _("Save"), "", ii::FileSave );
	CreateToolBarItem ( mpFileOprTb, wxID_SAVEAS, _("Save As..."), "", ii::FileSaveAs );
	CreateToolBarItem ( mpFileOprTb, wxID_CLOSE, _("Close"), "", ii::FileClose );

    mpItemOprTb = new wxAuiToolBar ( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
	mpItemOprTb->SetToolBitmapSize ( wxSize ( 16, 16 ) );

	CreateToolBarItem ( mpItemOprTb, ID_Menu_AddItem, _("Add"), _("Add a New Item"), 
		ii::EditAdd );

	CreateToolBarItem ( mpItemOprTb, wxID_DELETE, _("Delete"), 
		_("Move the Selected Item to the Recycle Bin"), ii::EditRemove );

	CreateToolBarItem ( mpItemOprTb, ID_Menu_UpdateItem, _("Update"), 
		_("Update Changes"), ii::EditUpdate );

	mpItemOprTb->AddSeparator();

	CreateToolBarItem ( mpItemOprTb, wxID_COPY, _("Copy"), "", ii::EditCopy );
	CreateToolBarItem ( mpItemOprTb, wxID_PASTE, _("Paste"), "", ii::EditPaste );

    mpFileOprTb->Realize();
	mpItemOprTb->Realize();

    mFrameMngr.AddPane ( mpFileOprTb, wxAuiPaneInfo().Name 
		( "File Operations" ).ToolbarPane().Top() );
    mFrameMngr.AddPane ( mpItemOprTb, wxAuiPaneInfo().Name 
		( "Item Operations" ).ToolbarPane().Top() );
}

void col::MainFrame::CreateMenuBar()
{
	typedef ColligereApp::IconIndex ii;

	wxMenuBar *mb = new wxMenuBar;

	/////////////////////////////////////////////////////
	// File menu
	/////////////////////////////////////////////////////

    wxMenu *file_menu = new wxMenu;
	
	file_menu->Append ( CreateMenuItem ( file_menu, wxID_NEW, 
		_("&New...\tCtrl+N"), _("New..."), ii::FileNew ) );

    file_menu->Append ( CreateMenuItem ( file_menu, wxID_OPEN, 
		_("&Open...\tCtrl+O"), _("Open"), ii::FileOpen ) );
	
	wxMenu *open_recent = new wxMenu;

	file_menu->AppendSubMenu ( open_recent, _("Open Recent"), _("Open &Recent") );

	mFileHistory.UseMenu ( open_recent );

	file_menu->AppendSeparator();

    file_menu->Append ( CreateMenuItem ( file_menu, wxID_SAVE, 
		_("&Save\tCtrl+S"), _("Save"), ii::FileSave ) );

    file_menu->Append ( CreateMenuItem ( file_menu, wxID_SAVEAS, 
		_("Save &As..."), _("Save As..."), ii::FileSaveAs ) );

	file_menu->AppendSeparator();

	wxMenu *_export = new wxMenu;

	_export->Append ( ID_Menu_ExportToXml, _("Export To XML\tCtrl+Alt+E") );

	file_menu->AppendSubMenu ( _export, _("Export"), _("&Export") );

	file_menu->AppendSeparator();

	wxMenu *import = new wxMenu;

	import->Append ( ID_Menu_ImportOrangeCdXml, _("Import From OrangeCD XML"),
		_("Import From OrangeCD XML") );

	import->Append ( ID_Menu_ImportCatraxxXml, _("Import From CATraxx XML"),
		_("Import From CATraxx XML") );

	import->Append ( ID_Menu_ImportColligereXml, _("Import From Colligere XML"),
		_("Import From Colligere XML") );

	import->Append ( ID_Menu_ImportDiscogs, _("Import From Discogs"),
		_("Import From Discogs") );

	file_menu->AppendSubMenu ( import, _("Import"), _("&Import") );

	file_menu->AppendSeparator();

	file_menu->Append ( ID_Menu_Properties, _("Properties\tAlt+Return"), 
		_("Database Properties") );

	file_menu->AppendSeparator();

	file_menu->Append ( CreateMenuItem ( file_menu, wxID_CLOSE,
		_("&Close\tCtrl+W"), _("Close"), ii::FileClose ) );

#ifdef __WXMAC__
	wxApp::s_macExitMenuItemId = wxID_EXIT;
#endif // __WXMAC__

	file_menu->Append ( CreateMenuItem ( file_menu, wxID_EXIT, 
		_("&Quit\tCtrl+Q"),_("Exit Colligere"), ii::Exit ) );

	mb->Append ( file_menu, _("&File") );

	/////////////////////////////////////////////////////
	// Edit menu
	/////////////////////////////////////////////////////	

	wxMenu *edit_menu = new wxMenu;

	edit_menu->Append ( CreateMenuItem ( edit_menu, ID_Menu_AddItem, 
		_("&Add\tCtrl+Alt+A"), _("Add a New Item"), ii::EditAdd ) );

	edit_menu->Append ( CreateMenuItem ( edit_menu, wxID_DELETE, _("&Delete\tDel"), 
		_("Move the Selected Item to the Recycle Bin"), ii::EditRemove ) );

	edit_menu->Append ( CreateMenuItem ( edit_menu, ID_Menu_UpdateItem, 
		_("&Update\tCtrl+U"), _("Update Changes"), ii::EditUpdate ) );

	edit_menu->AppendSeparator();

	edit_menu->Append ( CreateMenuItem ( edit_menu, wxID_COPY, 
		_("&Copy\tCtrl+C"), _("Copy"), ii::EditCopy ) );

	edit_menu->Append ( CreateMenuItem ( edit_menu, wxID_PASTE, 
		_("&Paste\tCtrl+V"), _("Paste the Previously Copied Item"), ii::EditPaste ) );

	edit_menu->AppendSeparator();

	edit_menu->Append ( wxID_CLEAR, _("Clear\tCtrl+Alt+C"), 
		_("Clear Input Fields") );

	edit_menu->AppendSeparator();

	edit_menu->Append ( ID_Menu_DeselectItem, _("Deselect\tCtrl+Shift+A"), 
		_("Deselect Item") );

	edit_menu->AppendSeparator();

#ifndef __WXMAC__
    //edit_menu->AppendSeparator();
#else
    wxApp::s_macPreferencesMenuItemId = ID_Menu_ViewPrefs;
#endif	// __WXMAC__

	wxMenuItem *pref_item = CreateMenuItem ( edit_menu, ID_Menu_ViewPrefs, 
		_("Pr&eferences..."), _("Edit Preferences"), ii::Configure );

	edit_menu->Append ( pref_item );

	mb->Append ( edit_menu, _("&Edit") );

	/////////////////////////////////////////////////////
	// Search menu
	/////////////////////////////////////////////////////

	wxMenu *search_menu = new wxMenu;

	wxMenuItem *search_item = CreateMenuItem ( edit_menu, ID_Menu_Search, 
		_("Search..."), _("Search Items"), ii::Search );

	search_menu->Append ( search_item );

	mb->Append ( search_menu, _("Search") );

	/////////////////////////////////////////////////////
	// View menu
	/////////////////////////////////////////////////////

	wxMenu *view_menu = new wxMenu;

	view_menu->Append ( ID_Menu_ViewLog, _("Log\tCtrl+Alt+L"), 
		_("View the Application Log"), wxITEM_CHECK );

	view_menu->Append ( ID_Menu_ViewItems, _("Database Items\tCtrl+Alt+D"), 
		_("View the Database Item List"), wxITEM_CHECK );

	view_menu->Append ( ID_Menu_ViewRecycleBin, _("Recycle Bin\tCtrl+Alt+R"), 
		_("View the Recycle Bin"), wxITEM_CHECK );

	view_menu->AppendSeparator();

	view_menu->Append ( ID_Menu_SearchFreeDb, _("Search FreeDb\tCtrl+Alt+F"), 
		_("Search CD Information From The FreeDb Server"), wxITEM_CHECK );

	view_menu->Append ( ID_Menu_SearchDiscogs, _("Search Discogs"),
		_("Search Release Information From Discogs.com"), wxITEM_CHECK );

	view_menu->AppendSeparator();

	view_menu->Append ( ID_Menu_SaveLayout, _("Save Layout\tCtrl+Alt+S"),
		_("Save Application Layout") );

	mb->Append ( view_menu, _("&View") );

	/////////////////////////////////////////////////////
	// Help menu
	/////////////////////////////////////////////////////

	wxMenu *help_menu = new wxMenu;

	/*
	wxMenuItem *help_item = CreateMenuItem ( help_menu, wxID_HELP, 
		_("&Index...\tF1"), _("Help"), wxITEM_NORMAL, ii::Help );
	help_menu->Append ( help_item );
	*/
#ifndef __WXMAC__
    //help_menu->AppendSeparator();
#else
    wxApp::s_macAboutMenuItemId = wxID_ABOUT;
#endif
	help_menu->Append ( wxID_ABOUT, _("About...\tShift+F1"), _("About Colligere") );
#ifdef __WXMAC__
    wxApp::s_macHelpMenuTitleName = _("&Help");
#endif
	mb->Append ( help_menu, _("&Help") );

	SetMenuBar ( mb );
}

wxAuiToolBar *col::MainFrame::GetFileOperationsToolBar() 
{ 
	return wxDynamicCast ( mFrameMngr.GetPane ( "File Operations" ).window, wxAuiToolBar );
}

wxAuiToolBar *col::MainFrame::GetItemOperationsToolBar() 
{ 
	return wxDynamicCast ( mFrameMngr.GetPane ( "Item Operations" ).window, wxAuiToolBar );
}

void col::MainFrame::CreateToolBarItem ( wxAuiToolBar *pParent, wxInt32 id,
										const wxString &rLabel,
										const wxString &rDescription,
										wxUint32 iconIndex )
{
	pParent->AddTool ( id, rLabel, wxGetApp().GetIcon ( iconIndex ), 
		rDescription.empty() ? rLabel : rDescription );
}

wxMenuItem *col::MainFrame::CreateMenuItem ( wxMenu *pParent, wxInt32 id,
											const wxString  &rLabel,
											const wxString  &rDescription,
											wxUint32 iconIndex, wxItemKind kind )
{
	wxASSERT ( kind == wxITEM_SEPARATOR || kind == wxITEM_NORMAL ||
		kind == wxITEM_CHECK || kind == wxITEM_RADIO );

	wxMenuItem *item = new wxMenuItem ( pParent, id, rLabel, rDescription, kind );
	
	if ( iconIndex > 0 )
	{
		item->SetBitmap ( wxGetApp().GetIcon ( iconIndex ) );
	}
	return item;
}

void col::MainFrame::LoadLayout()
{
	typedef ConfigVariable cvar;

	ConfigHandler &ch = ConfigHandler::Get();

	SetPosition ( ch.GetPosition ( cvar::MainFramePosition ) );

	const wxSize frame_size = ch.GetSize ( cvar::MainFrameSize );
	if ( frame_size != wxDefaultSize )
	{
		SetSize ( frame_size );
	}

	mpLogDlg->SetSize ( wxRect ( ch.GetPosition ( cvar::LogDialogPosition ), 
		ch.GetSize ( cvar::LogDialogSize ) ) );

	if ( ch.IsEnabled ( cvar::IsMainFrameMaximized ) ) 
	{
		Maximize();
	}

	const wxString layout ( ch.GetValue ( cvar::MainFrameWxAuiSettings ) );

	if ( !layout.empty() )
	{
		mFrameMngr.LoadPerspective ( layout, false );
	}
	mFrameMngr.Update();
}

void col::MainFrame::SaveLayout()
{
	typedef ConfigVariable cv;

	if ( !IsShown() ) return;

	ConfigHandler &ch = ConfigHandler::Get();

	ch.SetValue ( cv::IsMainFrameMaximized, IsMaximized() );
	ch.SetValue ( cv::MainFrameWxAuiSettings, mFrameMngr.SavePerspective() );

	ch.SetPosition ( cv::MainFramePosition, GetPosition() );
	ch.SetPosition ( cv::LogDialogPosition, mpLogDlg->GetPosition() );
	
	ch.SetSize ( cv::MainFrameSize, GetSize() );
	ch.SetSize ( cv::LogDialogSize, mpLogDlg->GetSize() );
}

const wxRect col::MainFrame::DetermineFrameSize() const
{
	const wxSize scr ( wxGetDisplaySize() );

	wxRect normal;
	if ( scr.x <= 800 ) 
	{
		normal.x = 40 / 2;
		normal.width = scr.x - 40;
	}
	else
	{
		normal.x = ( scr.x - 800 ) / 2;
		normal.width = 800;
	}
	if ( scr.y <= 600 ) 
	{
		normal.y = 80 / 2;
		normal.height = scr.y - 80;
	}
	else
	{
		normal.y = ( scr.y - 500 ) / 2;
		normal.height = 500;
	}
	return normal;
}

void col::MainFrame::EnableFileOperations ( bool enable )
{
	wxMenuBar *mb = GetMenuBar();

	mb->Enable ( wxID_CLOSE, enable );
	mb->Enable ( wxID_SAVE, enable );
	mb->Enable ( wxID_SAVEAS, enable );
	mb->Enable ( wxID_CLEAR, enable );
	mb->Enable ( ID_Menu_ViewItems, enable );
	mb->Enable ( ID_Menu_ViewItems, enable );
	mb->Enable ( ID_Menu_ViewRecycleBin, enable );
	mb->Enable ( ID_Menu_Search, enable );
	mb->Enable ( ID_Menu_Properties, enable );
	mb->Enable ( ID_Menu_ImportOrangeCdXml, enable );
	mb->Enable ( ID_Menu_ImportCatraxxXml, enable );
	mb->Enable ( ID_Menu_ImportColligereXml, enable );
	mb->Enable ( ID_Menu_ImportDiscogs, enable );
	mb->Enable ( ID_Menu_ExportToXml, enable );
	mb->Enable ( ID_Menu_SearchFreeDb, enable );
	mb->Enable ( ID_Menu_SearchDiscogs, enable );

	wxAuiToolBar *tb = wxDynamicCast ( mFrameMngr.GetPane 
		( "File Operations" ).window, wxAuiToolBar );

	tb->EnableTool ( wxID_CLOSE, enable );
	tb->EnableTool ( wxID_SAVE, enable );
	tb->EnableTool ( wxID_SAVEAS, enable );
}

void col::MainFrame::EnableItemOperations ( bool enable )
{
	EnableAdding ( enable );
	EnableCopy ( enable );
	EnablePaste ( enable );
	EnableDelete ( enable );
	EnableClearInputs ( enable );
	EnableUpdate ( enable );
}

void col::MainFrame::ConnectGuiEventHandlers()
{
	Connect ( wxID_NEW, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuNew ) ); 
	Connect ( wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuOpen ) ); 
	Connect ( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuExit ) ); 
	Connect ( wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuAbout ) ); 
	Connect ( wxID_CLOSE, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuClose ) );
	Connect ( wxID_SAVEAS, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuSaveAs ) );
	Connect ( wxID_COPY, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuCopy ) );
	Connect ( ID_Menu_Search, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuSearch ) );
	Connect ( ID_Menu_ViewLog, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuViewLog ) ); 
	Connect ( ID_Menu_SaveLayout, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuSaveLayout ) );

	Connect ( ID_Menu_AddItem, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( wxID_DELETE, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( wxID_SAVE, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( wxID_CLEAR, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( wxID_PASTE, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_ImportOrangeCdXml, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_ImportCatraxxXml, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_ImportDiscogs, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_ImportColligereXml, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_DeselectItem, wxEVT_COMMAND_MENU_SELECTED,
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_UpdateItem, wxEVT_COMMAND_MENU_SELECTED,
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_ViewItems, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) ); 
	Connect ( ID_Menu_ViewRecycleBin, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_ExportToXml, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_SearchFreeDb, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_SearchDiscogs, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenu ) );
	Connect ( ID_Menu_Properties, wxEVT_COMMAND_MENU_SELECTED, 
		wxCommandEventHandler ( MainFrame::OnMenuProperties ) );

	Connect ( wxID_FILE1, wxID_FILE9, wxEVT_COMMAND_MENU_SELECTED,
		wxCommandEventHandler ( MainFrame::OnMenuOpenRecent ) );
	
	Connect ( GetId(), wxEVT_CLOSE_WINDOW, wxCloseEventHandler 
		( MainFrame::OnClose ) );

	Connect ( ID_Menu_ViewPrefs, wxEVT_COMMAND_MENU_SELECTED,
		wxCommandEventHandler ( MainFrame::OnMenuPreferences ) );
}

void col::MainFrame::ConnectDatabaseEventHandlers()
{
	wxASSERT ( IsDatabaseOpened() );

	const wxUint32 db_id = mCurDb->GetId();

	Connect ( db_id, COLLIGERE_EVT_DATABASE_ITEM_ADD, 
		ColligereDatabaseEventHandlerFunction 
		( &MainFrame::OnDatabaseAddEvent ) ); 
	
	Connect ( db_id, COLLIGERE_EVT_DATABASE_ITEM_DELETE, 
		ColligereDatabaseEventHandlerFunction 
		( &MainFrame::OnDatabaseDeleteEvent ) );
	
	Connect ( db_id, COLLIGERE_EVT_DATABASE_ITEM_RESTORE, 
		ColligereDatabaseEventHandlerFunction 
		( &MainFrame::OnDatabaseRestoreEvent ) );

	Connect ( db_id, COLLIGERE_EVT_IMPORT_END,
		ColligereDataImporterEventHandlerFunction 
		( &MainFrame::OnImportEnd ) );

	Connect ( db_id, COLLIGERE_EVT_IMPORT_START,
		ColligereDataImporterEventHandlerFunction 
		( &MainFrame::OnImportStart ) );
}

bool col::MainFrame::CloseDatabase()
{
	wxASSERT ( IsDatabaseOpened() );

	if ( !mCurDb->Close() ) return false;
		
	SetStatusText ( _("Database Closed"), 0 );
	SetStatusText ( empty_string, 1 );
	SetStatusText ( empty_string, 2 );

	SetTitle ( wxGetApp().GetAppName() );

	EnableFileOperations ( false );
	EnableItemOperations ( false ); 

	mCurDb.reset();
	mFrameMngr.Update();

	return true;
}

bool col::MainFrame::CreateDatabase()
{
	wxFileDialog dlg ( this, _("Choose a file"), empty_string, empty_string, 
		_( "COL Files (*.col)|*.col|All Files (*.*)|*.*" ),
		wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

	if ( dlg.ShowModal() == wxID_OK )
	{
		if ( IsDatabaseOpened() && !CloseDatabase() )
		{
			return false;
		}
		
		const wxString path ( dlg.GetPath() );

		if ( wxFileExists ( path ) && !wxRemoveFile ( path ) )
		{
			wxLogError ( _("Unable to overwrite the file \"%s\"."), path );
			return false;
		}
		return OpenDatabase ( path );
	}
	return false;
}

bool col::MainFrame::OpenDatabase ( const wxString &rFileName )
{
	wxString file ( rFileName );

	if ( file.empty() )
	{
		wxFileDialog dlg ( this, _("Choose a file"), empty_string, empty_string, 
			_( "COL Files (*.col)|*.col|All Files (*.*)|*.*" ),
			wxFD_OPEN | wxFD_FILE_MUST_EXIST );

		ConfigHandler::Get().LoadLastDirectory 
			( ConfigVariable::LastOpenedDatabaseDir, dlg );

		if ( dlg.ShowModal() == wxID_OK )
		{
			file = dlg.GetPath();
			ConfigHandler::Get().SetValue ( ConfigVariable::LastOpenedDatabaseDir, 
				wxFileName ( file ).GetPath 
				( wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME ) );
		}
	}
	if ( file.empty() || ( IsDatabaseOpened() && !CloseDatabase() ) )
	{
		return false;
	}
	try
	{
		mCurDb = DatabaseInterfaceBasePtr ( new AudioDatabaseInterface );
		mCurDb->Open ( file, mFrameMngr );

		EnableFileOperations ( true );

		mFileHistory.AddFileToHistory ( file );
		ConfigHandler::Get().SaveFileHistory ( mFileHistory );
			
		SetStatusText ( _("Database Opened"), 0 );
		SetStatusText ( mCurDb->GetStatusText(1), 1 );
		SetStatusText ( mCurDb->GetStatusText(2), 2 );
		SetTitle ( mCurDb->GetTitleText() );

		mFrameMngr.Update();

		ConnectDatabaseEventHandlers();

		return true;
	}
	catch ( DatabaseError & )
	{
		mCurDb->Close();
		mCurDb.reset();
	}
	return false;
}

col::MainFrame &col::MainFrame::EnableAdding ( bool enable )
{
	GetMenuBar()->Enable ( ID_Menu_AddItem, enable );
	GetItemOperationsToolBar()->EnableTool ( ID_Menu_AddItem, enable );
	GetItemOperationsToolBar()->Refresh ( false );
	GetItemOperationsToolBar()->Update();
	return *this;
}

col::MainFrame &col::MainFrame::EnableUpdate ( bool enable )
{
	GetMenuBar()->Enable ( ID_Menu_UpdateItem, enable );
	GetItemOperationsToolBar()->EnableTool ( ID_Menu_UpdateItem, enable );
	GetItemOperationsToolBar()->Refresh ( false );
	GetItemOperationsToolBar()->Update();
	return *this;
}

col::MainFrame &col::MainFrame::EnableClearInputs ( bool enable )
{
	GetMenuBar()->Enable ( wxID_CLEAR, enable );
	GetItemOperationsToolBar()->EnableTool ( wxID_CLEAR, enable );
	GetItemOperationsToolBar()->Refresh ( false );
	GetItemOperationsToolBar()->Update();
	return *this;
}

col::MainFrame &col::MainFrame::EnableDeselectItem ( bool enable )
{
	GetMenuBar()->Enable ( ID_Menu_DeselectItem, enable );
	return *this;
}

col::MainFrame &col::MainFrame::EnableCopy ( bool enable )
{
	GetMenuBar()->Enable ( wxID_COPY, enable );
	GetItemOperationsToolBar()->EnableTool ( wxID_COPY, enable );
	GetItemOperationsToolBar()->Refresh ( false );
	GetItemOperationsToolBar()->Update();
	return *this;
}

col::MainFrame &col::MainFrame::EnablePaste ( bool enable )
{
	GetMenuBar()->Enable ( wxID_PASTE, enable );
	GetItemOperationsToolBar()->EnableTool ( wxID_PASTE, enable );
	GetItemOperationsToolBar()->Refresh ( false );
	GetItemOperationsToolBar()->Update();
	return *this;
}

col::MainFrame &col::MainFrame::EnableDelete ( bool enable )
{
	GetMenuBar()->Enable ( wxID_DELETE, enable );
	GetItemOperationsToolBar()->EnableTool ( wxID_DELETE, enable );
	GetItemOperationsToolBar()->Refresh ( false );
	GetItemOperationsToolBar()->Update();
	return *this;
}

bool col::MainFrame::IsDatabaseOpened() const
{
	return mCurDb.get() && mCurDb->IsOpened();
}

bool col::MainFrame::Exit()
{
	if ( IsDatabaseOpened() && !CloseDatabase() )
	{
		return false;
	}
	if ( ConfigHandler::Get().IsEnabled ( ConfigVariable::SaveLayoutOnExit ) )
	{
		SaveLayout();
	}
	if ( ConfigHandler::Get().IsEnabled ( ConfigVariable::DumpLogToFileOnExit ) )
	{
		mpLogDlg->SaveLog();
	}
	ConfigHandler::Get().SaveFileHistory ( mFileHistory );
	return true;
}


///////////////////////////////////////////
// Event handlers
///////////////////////////////////////////

void col::MainFrame::OnMenuAbout ( wxCommandEvent & )
{
	AboutDialog ( this ).ShowModal();
}

void col::MainFrame::OnMenuNew ( wxCommandEvent & )
{
	CreateDatabase();
}

void col::MainFrame::OnMenuOpen ( wxCommandEvent & )
{
	OpenDatabase();
}

void col::MainFrame::OnMenuClose ( wxCommandEvent & )
{
	wxASSERT ( IsDatabaseOpened() );
	CloseDatabase();
}

void col::MainFrame::OnMenuExit ( wxCommandEvent & )
{
	wxGetApp().ExitApp();
}

void col::MainFrame::OnMenuViewLog ( wxCommandEvent &rEvent )
{
	mpLogDlg->Show ( rEvent.IsChecked() );
	GetMenuBar()->Check ( ID_Menu_ViewLog, rEvent.IsChecked() );
}

void col::MainFrame::OnMenuSaveLayout ( wxCommandEvent &rEvent )
{
	if ( IsDatabaseOpened() )
	{
		mCurDb->DispatchGuiEvent ( rEvent.GetId() );
	}
	SaveLayout();
}

void col::MainFrame::OnMenuSaveAs ( wxCommandEvent &rEvent )
{
	wxASSERT ( IsDatabaseOpened() );
	mCurDb->DispatchGuiEvent ( rEvent.GetId() );
	SetTitle ( mCurDb->GetTitleText() );
	SetStatusText ( mCurDb->GetStatusText(2), 2 );
}

void col::MainFrame::OnMenu ( wxCommandEvent &rEvent )
{
	mCurDb->DispatchGuiEvent ( rEvent.GetId() );
}

void col::MainFrame::OnClose ( wxCloseEvent &rEvent )
{
	!wxGetApp().ExitApp() && rEvent.CanVeto() ? rEvent.Veto() : rEvent.Skip();
}

void col::MainFrame::OnMenuPreferences ( wxCommandEvent & )
{
	PreferencesDialog settings ( this );
	if ( settings.ShowModal() == wxID_OK )
	{
		wxToolTip::Enable ( ConfigHandler::Get().IsEnabled ( ConfigVariable::ShowToolTips ) );
	}
}

void col::MainFrame::OnMenuProperties ( wxCommandEvent & )
{
	wxASSERT ( IsDatabaseOpened() );

	wxDialog dlg;
	
	wxXmlResource::Get()->LoadDialog ( &dlg, this, "ID_Dialog_Properties" );

	const DatabaseProperties props ( mCurDb->GetProperties() );

	XRCCTRL ( dlg, "ID_StaticText_Path", wxStaticText )->SetLabel
		( props.GetFullPath() );
	XRCCTRL ( dlg, "ID_StaticText_Size", wxStaticText )->SetLabel
		( props.GetHumanReadableFileSize() );

	XRCCTRL ( dlg, "ID_StaticText_Created", wxStaticText )->SetLabel 
		( props.GetCreationTime() );
	XRCCTRL ( dlg, "ID_StaticText_Modified", wxStaticText )->SetLabel 
		( props.GetModificationTime() );

	if ( dlg.GetSizer() )
	{
		dlg.GetSizer()->SetSizeHints ( &dlg );
	}
	dlg.ShowModal();
}

void col::MainFrame::OnMenuCopy ( wxCommandEvent &rEvent )
{
	mCurDb->DispatchGuiEvent ( rEvent.GetId() );
	EnablePaste ( true );
}

void col::MainFrame::OnMenuOpenRecent ( wxCommandEvent &rEvent )
{
	const wxString file ( mFileHistory.GetHistoryFile ( rEvent.GetId() - wxID_FILE1 ) );

	if ( wxFileExists ( file ) )
	{
		OpenDatabase ( file );
	}
	else
	{
		wxLogError ( _("The file \"%s\" cannot be found."), file );
	}
}

void col::MainFrame::OnMenuSearch ( wxCommandEvent & )
{
	wxASSERT ( IsDatabaseOpened() );
	SearchDialog ( mCurDb.get() ).ShowModal();
}

void col::MainFrame::OnDatabaseAddEvent ( DatabaseEventBase & )
{

	SetStatusText ( mCurDb->GetStatusText(1), 1 );
}

void col::MainFrame::OnDatabaseRestoreEvent ( DatabaseEventBase & )
{
	SetStatusText ( mCurDb->GetStatusText(1), 1 );
}

void col::MainFrame::OnDatabaseDeleteEvent ( DatabaseEventBase & )
{
	SetStatusText ( mCurDb->GetStatusText(1), 1 );
}

void col::MainFrame::OnImportStart ( DataImporterEvent & )
{
	// This no longer works after updating to wx2.9.0-svn.
	if ( !Disconnect ( mCurDb->GetId(), COLLIGERE_EVT_DATABASE_ITEM_ADD ) )
	{
		wxFAIL;
	}
}

void col::MainFrame::OnImportEnd ( DataImporterEvent & )
{
	Connect ( mCurDb->GetId(), COLLIGERE_EVT_DATABASE_ITEM_ADD, 
		ColligereDatabaseEventHandlerFunction 
		( &MainFrame::OnDatabaseAddEvent ) ); 

	SetStatusText ( mCurDb->GetStatusText(1), 1 );
}

//////////////////////////////////////////////
// ColligereDatabaseDropTarget
//////////////////////////////////////////////

col::DatabaseDropTarget::DatabaseDropTarget ( MainFrame *pParent ) : mpParent ( pParent ) 
{ 
}

bool col::DatabaseDropTarget::OnDropFiles ( wxCoord, wxCoord, 
										   const wxArrayString &rFileNames )
{
	for ( size_t i = 0; i < rFileNames.GetCount(); ++i ) 
	{
		if ( !wxFileName ( rFileNames[i] ).IsDir() ) 
		{
			// Only open the first file since multiple files are not supported (yet?).
			mpParent->OpenDatabase ( rFileNames[i] );
			return true;
		}
	}
	return false;
}